const uint8_t *bytes,
uint32_t len);
+bool SCJbSetPrintAsciiString(struct JsonBuilder *js,
+ const char *key,
+ const uint8_t *bytes,
+ uint32_t len);
+
bool jb_set_base64(struct JsonBuilder *js,
const char *key,
const uint8_t *bytes,
}
}
+ /// Set a key with a string value taking only ascii-printable bytes.
+ /// Non-printable characters are replaced by a dot `.`, except
+ /// CR and LF which are escaped the regular json way \r and \n
+ pub fn set_print_ascii(&mut self, key: &str, val: &[u8]) -> Result<&mut Self, JsonError> {
+ match self.current_state() {
+ State::ObjectNth => {
+ self.push(',')?;
+ }
+ State::ObjectFirst => {
+ self.set_state(State::ObjectNth);
+ }
+ _ => {
+ debug_validate_fail!("invalid state");
+ return Err(JsonError::InvalidState);
+ }
+ }
+ self.push('"')?;
+ self.push_str(key)?;
+ self.push_str("\":\"")?;
+ for &x in val.iter() {
+ match x {
+ b'\r' => {
+ self.push_str("\\r")?;
+ }
+ b'\n'=> {
+ self.push_str("\\n")?;
+ }
+ b'"'=> {
+ self.push_str("\\\"")?;
+ }
+ b'\\'=> {
+ self.push_str("\\\\")?;
+ }
+ _ => {
+ if !x.is_ascii() || x.is_ascii_control() {
+ self.push('.')?;
+ } else {
+ self.push(x as char)?;
+ }
+ }
+ }
+ }
+ self.push('"')?;
+ Ok(self)
+ }
+
/// Set a key and a string value (from bytes) on an object, with a limited size
pub fn set_string_from_bytes_limited(&mut self, key: &str, val: &[u8], limit: usize) -> Result<&mut Self, JsonError> {
let mut valtrunc = Vec::new();
return false;
}
+#[no_mangle]
+pub unsafe extern "C" fn SCJbSetPrintAsciiString(
+ js: &mut JsonBuilder, key: *const c_char, bytes: *const u8, len: u32,
+) -> bool {
+ if bytes.is_null() || len == 0 {
+ return false;
+ }
+ if let Ok(key) = CStr::from_ptr(key).to_str() {
+ let val = std::slice::from_raw_parts(bytes, len as usize);
+ return js.set_print_ascii(key, val).is_ok();
+ }
+ return false;
+}
+
#[no_mangle]
pub unsafe extern "C" fn jb_set_base64(
js: &mut JsonBuilder, key: *const c_char, bytes: *const u8, len: u32,
}
if (json_output_ctx->flags & LOG_JSON_PAYLOAD) {
- uint8_t printable_buf[p->payload_len + 1];
- uint32_t offset = 0;
- PrintStringsToBuffer(printable_buf, &offset,
- p->payload_len + 1,
- p->payload, p->payload_len);
- printable_buf[p->payload_len] = '\0';
- jb_set_string(js, "payload_printable", (char *)printable_buf);
+ SCJbSetPrintAsciiString(js, "payload_printable", p->payload, p->payload_len);
}
}
}
if (json_output_ctx->flags & LOG_JSON_PAYLOAD) {
- uint8_t printable_buf[cbd.payload->offset + 1];
- uint32_t offset = 0;
- PrintStringsToBuffer(printable_buf, &offset, sizeof(printable_buf), cbd.payload->buffer,
- cbd.payload->offset);
- jb_set_string(jb, "payload_printable", (char *)printable_buf);
+ SCJbSetPrintAsciiString(
+ jb, "payload_printable", cbd.payload->buffer, cbd.payload->offset);
}
return true;
}
if (cbd.payload->offset) {
jb_set_base64(jb, "payload", cbd.payload->buffer, cbd.payload->offset);
- uint8_t printable_buf[cbd.payload->offset + 1];
- uint32_t offset = 0;
- PrintStringsToBuffer(printable_buf, &offset, sizeof(printable_buf), cbd.payload->buffer,
- cbd.payload->offset);
- jb_set_string(jb, "payload_printable", (char *)printable_buf);
+ SCJbSetPrintAsciiString(jb, "payload_printable", cbd.payload->buffer, cbd.payload->offset);
jb_set_bool(jb, "complete", complete);
}
}
const uint32_t log_data_len = MIN(data_len, 256);
jb_set_base64(js, "payload", data, log_data_len);
- uint8_t printable_buf[log_data_len + 1];
- uint32_t o = 0;
- PrintStringsToBuffer(printable_buf, &o, log_data_len + 1, data, log_data_len);
- printable_buf[log_data_len] = '\0';
- jb_set_string(js, "payload_printable", (char *)printable_buf);
+ SCJbSetPrintAsciiString(js, "payload_printable", data, log_data_len);
#if 0
char pretty_buf[data_len * 4 + 1];
pretty_buf[0] = '\0';
static void BodyPrintableBuffer(JsonBuilder *js, HtpBody *body, const char *key)
{
if (body->sb != NULL && body->sb->region.buf != NULL) {
- uint32_t offset = 0;
const uint8_t *body_data;
uint32_t body_data_len;
uint64_t body_offset;
return;
}
- uint8_t printable_buf[body_data_len + 1];
- PrintStringsToBuffer(printable_buf, &offset,
- sizeof(printable_buf),
- body_data, body_data_len);
- if (offset > 0) {
- jb_set_string(js, key, (char *)printable_buf);
- }
+ SCJbSetPrintAsciiString(js, key, body_data, body_data_len);
}
}
PrintStringsToBuffer(keybuf, &offset,
sizeof(keybuf),
pv->key, pv->key_len);
- uint32_t len = pv->value_len;
- uint8_t printable_buf[len + 1];
- offset = 0;
- PrintStringsToBuffer(printable_buf, &offset,
- sizeof(printable_buf),
- pv->value, pv->value_len);
- jb_set_string(js_vars, (char *)keybuf, (char *)printable_buf);
+ SCJbSetPrintAsciiString(js_vars, (char *)keybuf, pv->value, pv->value_len);
} else {
const char *varname = VarNameStoreLookupById(pv->id, VAR_TYPE_PKT_VAR);
- uint32_t len = pv->value_len;
- uint8_t printable_buf[len + 1];
- uint32_t offset = 0;
- PrintStringsToBuffer(printable_buf, &offset,
- sizeof(printable_buf),
- pv->value, pv->value_len);
- jb_set_string(js_vars, varname, (char *)printable_buf);
+ SCJbSetPrintAsciiString(js_vars, varname, pv->value, pv->value_len);
}
jb_close(js_vars);
}
break;
}
- uint32_t len = fv->data.fv_str.value_len;
- uint8_t printable_buf[len + 1];
- uint32_t offset = 0;
- PrintStringsToBuffer(printable_buf, &offset,
- sizeof(printable_buf),
- fv->data.fv_str.value, fv->data.fv_str.value_len);
-
jb_start_object(js_flowvars);
- jb_set_string(js_flowvars, varname, (char *)printable_buf);
+ SCJbSetPrintAsciiString(
+ js_flowvars, varname, fv->data.fv_str.value, fv->data.fv_str.value_len);
jb_close(js_flowvars);
}
} else if (fv->datatype == FLOWVAR_TYPE_STR && fv->key != NULL) {
sizeof(keybuf),
fv->key, fv->keylen);
- uint32_t len = fv->data.fv_str.value_len;
- uint8_t printable_buf[len + 1];
- offset = 0;
- PrintStringsToBuffer(printable_buf, &offset,
- sizeof(printable_buf),
- fv->data.fv_str.value, fv->data.fv_str.value_len);
-
jb_start_object(js_flowvars);
- jb_set_string(js_flowvars, (const char *)keybuf, (char *)printable_buf);
+ SCJbSetPrintAsciiString(js_flowvars, (const char *)keybuf, fv->data.fv_str.value,
+ fv->data.fv_str.value_len);
jb_close(js_flowvars);
} else if (fv->datatype == FLOWVAR_TYPE_INT) {
const char *varname = VarNameStoreLookupById(fv->idx,